﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Drawing;
using System.Threading;

namespace Omega.Game.Framework
{
    [Serializable]
    public sealed class Layer : Interfaces.IRender
    {
        public Tile[ , ] Tiles;
        int anindex = 0;
        int animFrameMax = 5;
        int currentFrame = 0;
        public int MaxAnimeFrames = 3;

        internal int Width { get { return this.Tiles.GetLength( 1 ); } }
        internal int Height { get { return this.Tiles.GetLength( 0 ); } }

        public Color Tone = new Color();

        public float Deph { get; set; }
        Tilemap owner;

        public Layer( Tilemap ow , int width , int height , float deph )
        {
            this.owner = ow;
            this.Tiles = new Tile[ height , width ];
            for ( int x = 0 ; x < width ; x++ )
            {
                for ( int y = 0 ; y < height ; y++ )
                {
                    Tiles[ y , x ] = new Tile( x * 32 , y * 32 , -1 , -1 , String.Empty , deph );
                }
            }

            this.Deph = deph;
        }


        public void Resize( int width , int height )
        {

            Tile[ , ] temptiles = new Tile[ height , width ];
            Tile ot;
            for ( int x = 0 ; x < width ; x++ )
            {
                for ( int y = 0 ; y < height ; y++ )
                {
                    ot = GetTileAt( x , y );

                    if ( ot != null )
                    {
                        temptiles[ y , x ] = ot;
                    }
                    else
                    {
                        temptiles[ y , x ] = new Tile( x * 32 , y * 32 , -1 , -1 , String.Empty , Deph );
                    }
                }
            }

            Tiles = new Tile[ height , width ];

            for ( int x = 0 ; x < width ; x++ )
            {
                for ( int y = 0 ; y < height ; y++ )
                {
                    Tiles[ y , x ] = temptiles[ y , x ];
                }

            }

        }
        public Tile GetTileAt( int x , int y )
        {
            if ( x >= this.Tiles.GetLength( 1 ) || y >= this.Tiles.GetLength( 0 )
                || x < 0 || y < 0 )
                return null;

            return Tiles[ y , x ];
        }

        public void SetValue( int x , int y , int valuex , int valuey , string tilesetname )
        {
            this.Tiles[ y , x ].TileID = 0;
            this.Tiles[ y , x ].SetValue( valuex , valuey , tilesetname );

            ThreadPool.QueueUserWorkItem( ( o ) => UpdateAutoTiles( ) );

        }
        public void SetValue( int x , int y , int ID , string tilesetName )
        {
            Tile oTile = GetTileAt( x , y );

            oTile.TilesetName = tilesetName;
            oTile.TileID = ID;

            ThreadPool.QueueUserWorkItem( ( o ) => UpdateAutoTiles( ) );
        }

        public void UpAutoTiles( int x , int y , Tile tile = null )
        {
            Tile oTile = tile == null ? GetTileAt( x , y ) : tile;

            //Obtenho os Tiles Principais
            Tile lftTile = GetTileAt( x - 1 , y );
            Tile rgtTile = GetTileAt( x + 1 , y );
            Tile tpTile = GetTileAt( x , y - 1 );
            Tile dnTile = GetTileAt( x , y + 1 );

            #region TopTile

            //Se o  Tile Acima nao for nulo e for igual ao tile em questao
            if ( tpTile != null && tpTile.IsEqual( oTile ) )
            {
                #region Tile a Direita
                //Vamos verificar as laterais
                //Se a direita for igual
                if ( rgtTile != null && rgtTile.IsNotEmpty && rgtTile.IsEqual( oTile ) )
                {
                    //Vamos verificar o tile na diag a direita acima
                    Tile diagTile = GetTileAt( x + 1 , y - 1 );

                    //Se o tile na diag cima, direita nao for nulo
                    //E se ele for igual
                    if ( diagTile != null && diagTile.IsEqual( oTile ) )
                    {
                        oTile.TopRightCorner = new int[ ] { 48 , 64 };
                    }
                    else// se nao for igual o tile na diag
                    {
                        oTile.TopRightCorner = new int[ ] { 80 , 0 };

                    }
                } //  Se o tile a Direita for diferente
                else
                {

                    oTile.TopRightCorner = new int[ ] { 80 , 64 };
                    oTile.ButtomRightCorner = new int[ ] { 80 , 80 };
                }
                #endregion

                #region Tile a esquerda

                if ( lftTile != null && lftTile.IsNotEmpty && lftTile.IsEqual( oTile ) )
                {
                    //Vamos verificar o tile na diag a direita acima
                    Tile diagTile = GetTileAt( x - 1 , y - 1 );

                    //Se o tile na diag cima, esuerda nao for nulo
                    //E se ele for igual
                    if ( diagTile != null && diagTile.IsNotEmpty && diagTile.IsEqual( oTile ) )
                    {
                        oTile.TopLeftCorner = new int[ ] { 32 , 64 };
                    }
                    else// se nao for igual o tile na diag
                    {

                        tile.TopLeftCorner = new int[ ] { 64 , 0 };
                    }
                } //  Se o tile a esqerda for diferente
                else
                {

                    oTile.TopLeftCorner = new int[ ] { 0 , 64 };
                    oTile.ButtomRightCorner = new int[ ] { 0 , 80 };
                }

                #endregion


            }
            //Se acima nao for igual
            else
            {
                if ( lftTile != null && lftTile.IsEqual( oTile ) )
                {
                    oTile.TopLeftCorner = new int[ ] { 32 , 32 };

                }
                else oTile.TopLeftCorner = new int[ ] { 0 , 32 };

                if ( rgtTile != null && rgtTile.IsEqual( oTile ) )
                {
                    oTile.TopRightCorner = new int[ ] { 64 , 32 };

                }
                else
                    oTile.TopRightCorner = new int[ ] { 80 , 32 };
            }
            #endregion


            #region DownTile
            //Se o Tile Abaixo for igual
            if ( dnTile != null && dnTile.IsEqual( oTile ) )
            {

                // Verifica o tile a esquerda
                if ( lftTile != null && lftTile.IsEqual( oTile ) )
                {
                    Tile diagtile = GetTileAt( x - 1 , y + 1 );
                    //verifica o Tile na diagonal
                    if ( diagtile != null && diagtile.IsEqual( oTile ) )
                    {
                        oTile.ButtomLeftCorner = new int[ ] { 32 , 80 };

                    }
                    //se o tile na diagonal for nulo
                    else
                    {
                        oTile.ButtomLeftCorner = new int[ ] { 64 , 16 };
                    }
                }
                else
                {
                    oTile.ButtomLeftCorner = new int[ ] { 0 , 80 };

                }

                // Verifica o tile na direita
                if ( rgtTile != null && rgtTile.IsEqual( oTile ) )
                {
                    Tile diagtile = GetTileAt( x + 1 , y + 1 );
                    //verifica o Tile na diagonal
                    if ( diagtile != null && diagtile.IsEqual( oTile ) )
                    {
                        oTile.ButtomRightCorner = new int[ ] { 48 , 80 };
                    }
                    //se o tile na diagonal for nulo
                    else
                    {
                        oTile.ButtomRightCorner = new int[ ] { 80 , 16 };
                    }
                }
                else
                {
                    oTile.ButtomRightCorner = new int[ ] { 80 , 80 };
                }

            }

            //Se for diferente ou nulo
            else
            {
                if ( rgtTile != null && rgtTile.IsEqual( oTile ) )
                {
                    oTile.ButtomRightCorner = new int[ ] { 48 , 112 };
                }
                else
                {
                    oTile.ButtomRightCorner = new int[ ] { 80 , 112 };
                }

                if ( lftTile != null && lftTile.IsEqual( oTile ) )
                {

                    oTile.ButtomLeftCorner = new int[ ] { 32 , 112 };
                }
                else

                { oTile.ButtomLeftCorner = new int[ ] { 0 , 112 }; }

            }

            #endregion


        }

        public void UpdateAutoTiles( )
        {
            for ( int x = 0 ; x < this.Width ; x++ )
            {
                for ( int y = 0 ; y < Height ; y++ )
                {
                    Tile ot = GetTileAt( x , y );
                    if ( ot != null && ot.TileID == 1 )
                        UpAutoTiles( x , y , ot );
                }
            }
        }



        //public override void Draw( SpriteBatch sp )
        //{
        //    int _x = Graphics.Runtime.CameraOffSet_X > 0 ? Graphics.Runtime.CameraOffSet_X - 1 : 0;
        //    int _y = Graphics.Runtime.CameraOffSet_Y > 0 ? Graphics.Runtime.CameraOffSet_Y - 1 : 0;
        //    int _width = Graphics.Runtime.Width / 32;
        //    int _heght = Graphics.Runtime.Height / 32;

        //    int grWidth = Graphics.Runtime.Width;
        //    int grHeight = Graphics.Runtime.Height;
        //    int SafeAreaWidth = ( grWidth - ( int )Graphics.Runtime.Camera.ViewPosition.X ) / 32 + 1;
        //    int SafeAreaHeight = ( grHeight - ( int )Graphics.Runtime.Camera.ViewPosition.Y ) / 32 + 1;

        //    anindex++;

        //    if ( anindex > animFrameMax )
        //    {
        //        anindex = 0;
        //        currentFrame++;
        //        if ( currentFrame > MaxAnimeFrames ) currentFrame = 0;
        //    }


        //    for ( int x = _x ; x < Width ; x++ )
        //    {
        //        for ( int y = _y ; y < Height ; y++ )
        //        {
        //            if ( x <= SafeAreaWidth && y < SafeAreaHeight )
        //            {
        //                Tile oTile = GetTileAt( x , y );


        //                if ( oTile != null && oTile.IsNotEmpty )
        //                {
        //                    if ( oTile.TileID == 0 )
        //                    {

        //                        sp.Draw( owner.GetTexture( oTile.TilesetName , 0 ) ,
        //                            oTile.Position , new Rectangle( oTile.tilex , oTile.tiley , 32 , 32 ) , Tone );
        //                    }
        //                    else
        //                    {
        //                        int frame = currentFrame;
        //                        if ( owner.GetTexture( oTile.TilesetName , 1 ).Width <= 96 ) frame  = 0;

        //                        sp.Draw( owner.GetTexture( oTile.TilesetName , 1 ) ,
        //                             new Rectangle( ( int )oTile.Position.X ,
        //                                 ( int )oTile.Position.Y , 16 , 16 ) , new Rectangle( oTile.TopLeftCorner[ 0 ] + ( frame * 96 ) , oTile.TopLeftCorner[ 1 ] , 16 , 16 ) , Tone );

        //                        sp.Draw( owner.GetTexture( oTile.TilesetName , 1 ) ,
        //                             new Rectangle( ( int )oTile.Position.X + 16 ,
        //                                 ( int )oTile.Position.Y , 16 , 16 ) , new Rectangle( oTile.TopRightCorner[ 0 ] + ( frame * 96 ) , oTile.TopRightCorner[ 1 ] , 16 , 16 ) , Tone );


        //                        sp.Draw( owner.GetTexture( oTile.TilesetName , 1 ) ,
        //                             new Rectangle( ( int )oTile.Position.X ,
        //                                 ( int )oTile.Position.Y + 16 , 16 , 16 ) , new Rectangle( oTile.ButtomLeftCorner[ 0 ] + ( frame * 96 ) , oTile.ButtomLeftCorner[ 1 ] , 16 , 16 ) , Tone );

        //                        sp.Draw( owner.GetTexture( oTile.TilesetName , 1 ) ,
        //                           new Rectangle( ( int )oTile.Position.X + 16 ,
        //                               ( int )oTile.Position.Y + 16 , 16 , 16 ) , new Rectangle( oTile.ButtomRightCorner[ 0 ] + ( frame * 96 ) , oTile.ButtomRightCorner[ 1 ] , 16 , 16 ) , Tone );

        //                    }
        //                }


        //            }

        //        }
        //    }

        //    base.Draw( sp );
        //}


        public bool NeedDraw
        {
            get
            {
                throw new NotImplementedException();
            }
            set
            {
                throw new NotImplementedException();
            }
        }

        public bool Disposed
        {
            get
            {
                throw new NotImplementedException();
            }
            set
            {
                throw new NotImplementedException();
            }
        }

        public void CreateRender()
        {
            throw new NotImplementedException();
        }

        public void Draw()
        {
            throw new NotImplementedException();
        }

        public void Dispose()
        {
            throw new NotImplementedException();
        }
    }
}
